﻿using System;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MugenInjection;
using MugenInjection.Attributes;
using MugenInjection.Exceptions;
using MugenInjection.Infrastructure;
using Should;

namespace MugenInjectionTest.Attributes
{
    [TestClass]
    public class NamedParameterAttributeTest : TestBase
    {
        [TestMethod]
        public void NamedAttributeTest()
        {
            using (var injector = GetInjector())
            {
                injector.Bind<NamedAttributeClass>().ToSelf();
                Action action = () => injector.Get<NamedAttributeClass>();
                action.ShouldThrow<BindingNotFoundException>();

                const string array = "Array";
                const string property = "property";
                const string constructorParameter = "constructorParameter";
                const string methodParameter = "methodParameter";

                injector.Bind<string>().ToConstant("commonstring");
                injector.Bind<string>().ToConstant(property).NamedBinding("Property");
                injector.Bind<string>().ToConstant(constructorParameter).NamedBinding("parameter");
                injector.Bind<string>().ToConstant(methodParameter).NamedBinding("methodParameter");
                //Array
                injector.Bind<string>().ToConstant(array).NamedBinding("Array");
                injector.Bind<string>().ToConstant(array).NamedBinding("Array");

                var namedAttributeClass = injector.Get<NamedAttributeClass>();

                namedAttributeClass.Property.ShouldEqual(property);
                namedAttributeClass.MethodParameter.ShouldEqual(methodParameter);
                namedAttributeClass.ConstructorParameter.ShouldEqual(constructorParameter);
                namedAttributeClass.Strings.Length.ShouldEqual(2);
                namedAttributeClass.Strings[0].ShouldEqual(array);
                namedAttributeClass.Strings[1].ShouldEqual(array);
            }
        }

        [TestMethod]
        public void NamedAttributeWithComplexTypesTest()
        {
            using (var injector = GetInjector())
            {
                const string value = "constName";
                const string constName = "parameter";
                injector.Bind<NamedAttributeClassWithSetting>().ToSelf();
                injector.Bind<string>().ToConstant(value).NamedBinding(constName);

                var classWithSetting = injector.Get<NamedAttributeClassWithSetting>();
                var result = classWithSetting.ConstructorParameter;
                result.SpecialParameters[SpecialParameterKeys.KeyedBindingParameter]
                    .ShouldEqual(constName);
                result.Value.ShouldEqual(value);
            }
        }

        #region Nested type: NamedAttributeClass

        public class NamedAttributeClass
        {
            public NamedAttributeClass([NamedParameter("parameter")] string parameter)
            {
                ConstructorParameter = parameter;
            }

            public string ConstructorParameter { get; set; }

            public string MethodParameter { get; set; }

            [NamedParameter("Property")]
            public string Property { get; set; }

            [NamedParameter("Array")]
            public string[] Strings { get; set; }

            [Inject]
            public void Method([NamedParameter("methodParameter")] string methodParameter)
            {
                MethodParameter = methodParameter;
            }
        }

        public class NamedAttributeClassWithSetting
        {
            public NamedAttributeClassWithSetting([NamedParameter("parameter")] WithSettings<string> parameter)
            {
                ConstructorParameter = parameter;
            }

            public WithSettings<string> ConstructorParameter { get; set; }
        }

        #endregion
    }
}